home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.1 (Developer) [x86] / NeXT Step 3.1 Intel dev.cdr.dmg / NextDeveloper / Examples / UNIX / Floppy / fdform.c next >
Encoding:
C/C++ Source or Header  |  1993-02-18  |  12.4 KB  |  543 lines

  1. /* fdform - Floppy format utility
  2.  *
  3.  *    usage:   fdform device [b=blocksize] [d=density] [g=gap3_length]
  4.  *
  5.  *        blocksize must be 512 or 1024.
  6.  *        density is in Kbytes. Current legal values are 720, 1440,
  7.  *            and 2880. Default is max density allowable for media.
  8.  *
  9.  *
  10.  *    You may freely copy, distribute and reuse the code in this example.
  11.  *    NeXT disclaims any warranty of any kind, expressed or implied, as to
  12.  *    its fitness for any particular use.
  13.  */
  14.  
  15. #import <fcntl.h>
  16. #import <stdio.h>
  17. #import <sys/types.h>
  18. #import <mach/mach.h>
  19. #import <bsd/dev/scsireg.h>
  20. /*
  21.  * m68k is worst case as far as alignment restrictions...
  22.  */
  23. #ifdef    m68k
  24. #import <bsd/dev/m68k/dma.h>
  25. #endif    m68k
  26. #import <sys/param.h>
  27. #import <signal.h>
  28. #import <bsd/dev/fd_extern.h>
  29. #import <libc.h>
  30. #import <stdlib.h>
  31. #import <sys/file.h>
  32.  
  33. void usage(char **argv);
  34. int format_disk(int fd, int live_fd, struct fd_format_info *finfop);
  35. int format_track(int fd, int cylinder, int head, 
  36.     struct fd_format_info *finfop);
  37. int recalibrate(int fd, struct fd_format_info *fip);
  38. int seek_com(int fd, int track, struct fd_format_info *finfop, int density);
  39. int do_ioc(int fd, fd_ioreq_t fdiop);
  40. int fd_rw(int fd,
  41.     int block,
  42.     int block_count,
  43.     u_char *addrs,
  44.     boolean_t read_flag,
  45.     struct fd_format_info *finfop);
  46. void format_abort();
  47.  
  48. #ifndef    TRUE
  49. #define TRUE    (1)
  50. #endif    TRUE
  51. #ifndef    FALSE
  52. #define FALSE    (0)
  53. #endif    FALSE
  54.  
  55. u_char             *vfy_buf;
  56. struct format_data     *fdp;
  57. int            cyls_to_format = 0;
  58. int             fmt_gap3_length = -1;
  59. int             fd;
  60. int            live_fd;
  61. struct fd_format_info     format_info;
  62.  
  63. main(int argc, char *argv[]) {
  64.  
  65.     char             c[80];
  66.     int             arg;
  67.     char             ch;
  68.     int            max_density;
  69.     int             rtn;
  70.     kern_return_t         krtn;
  71.     int            format_data_size;
  72.     struct fd_sectsize_info *ssip;
  73.     int             density = FD_DENS_NONE;
  74.     int            blocksize = 512;
  75.     
  76.     if(argc<2) 
  77.         usage(argv);
  78.     fd = open(argv[1], O_RDWR, 0);
  79.     if(fd <= 0) {
  80.         printf("Opening %s:\n", argv[1]);
  81.         perror("open");
  82.         exit(1);
  83.     }
  84.     
  85.     /*
  86.      * Open the live partition for read/verify.
  87.      */
  88.     argv[1][strlen(argv[1]) - 1] = 'b';
  89.     live_fd = open(argv[1], O_RDONLY, 0);
  90.     if(live_fd <= 0) {
  91.         printf("Opening %s:\n", argv[1]);
  92.         perror("open");
  93.         exit(1);
  94.     }
  95.     for(arg=2; arg<argc; arg++) {
  96.         ch = argv[arg][0];
  97.         switch(ch) {
  98.             case 'd':
  99.                 density = atoi(&argv[arg][2]);
  100.             switch(density) {
  101.                 case 720:
  102.                     density = FD_DENS_1;
  103.                 break;
  104.                 case 1440:
  105.                     density = FD_DENS_2;
  106.                 break;
  107.                 case 2880:
  108.                     density = FD_DENS_4;
  109.                 break;
  110.                 default:
  111.                     usage(argv);
  112.             }
  113.             break;
  114.             case 'b':
  115.                 blocksize = atoi(&argv[arg][2]);
  116.             if((blocksize != 512) && (blocksize != 1024))
  117.                 usage(argv);
  118.             break;
  119.             
  120.             case 'g':
  121.                 fmt_gap3_length = atoi(&argv[arg][2]);
  122.             break;
  123.             
  124.             case 'n':
  125.                 cyls_to_format = atoi(&argv[arg][2]);
  126.             break;
  127.             
  128.             default:
  129.                 usage(argv);
  130.         }
  131.     }
  132.     /*
  133.      * find out what kind of disk is installed, then ensure that we
  134.      * haven't been asked to format a bogus density for this disk.
  135.      */
  136.     if(ioctl(fd, FDIOCGFORM, &format_info)) {
  137.         perror("ioctl(FDIOCGFORM)");
  138.         return(1);
  139.     }
  140.     if(density > format_info.disk_info.max_density) {
  141.         printf("\nMaximum Legal Density for this disk is ");
  142.         switch(format_info.disk_info.max_density) {
  143.             case FD_DENS_1:
  144.                 printf("1 (720 KBytes formatted)\n");
  145.             exit(1);
  146.             case FD_DENS_2:
  147.                 printf("2 (1.44 MByte formatted)\n");
  148.             exit(1);
  149.             case FD_DENS_4:
  150.                 printf("4 (2.88 MByte formatted)\n");
  151.             exit(1);
  152.         }
  153.     }
  154.     if(density == FD_DENS_NONE) 
  155.         density = format_info.disk_info.max_density;
  156.  
  157.     printf("Formatting disk %s: \n", argv[1]);
  158.     printf("    blocksize   = 0x%x\n", blocksize);
  159.     printf("    density     = ");
  160.     switch(density) {
  161.         case FD_DENS_1:
  162.             printf("720 KBytes\n");
  163.         break;
  164.         case FD_DENS_2:
  165.         printf("1.44 MByte\n");
  166.         break;
  167.         case FD_DENS_4:
  168.         printf("2.88 MByte\n");
  169.         break;
  170.     }    
  171.     /*
  172.      * If user hasn't specified gap length, use default provided by driver
  173.      */
  174.     if(fmt_gap3_length < 0)
  175.         fmt_gap3_length = format_info.sectsize_info.fmt_gap_length;
  176.     printf("    gap3 length = %d(d)\n", fmt_gap3_length);
  177.  
  178.     /*
  179.      * Generate a new format_info. Have the driver calculate physical 
  180.      * parameters based on sector size and density.  If we abort the 
  181.      * format for any reason, we'll mark the disk unformatted.
  182.      */
  183.     if(ioctl(fd, FDIOCSDENS, &density)) {
  184.         perror("ioctl(FDIOCSDENS)");
  185.         return(1);
  186.     }
  187.     if(ioctl(fd, FDIOCSSIZE, &blocksize)) {
  188.         perror("ioctl(FDIOCSSIZE)");
  189.         return(1);
  190.     }
  191.  
  192.     /*
  193.      * This returns all the current parameters, based on what we just
  194.      * told the driver.
  195.      */
  196.     if(ioctl(fd, FDIOCGFORM, &format_info)) {
  197.         perror("ioctl(FDIOCGFORM)");
  198.         format_abort();
  199.     }
  200.     
  201.     /*
  202.      * Get page-aligned buffers for all the reading and writing we'll 
  203.      * be doing.
  204.      */
  205.     ssip = &format_info.sectsize_info;
  206.     krtn = vm_allocate(task_self(), 
  207.             (vm_address_t *)&vfy_buf,
  208.             ssip->sects_per_trk * ssip->sect_size,
  209.             TRUE);
  210.     if(krtn) {
  211.         printf("\n...Couldn't allocate track buffer\n");
  212.         format_abort();
  213.     }
  214.     format_data_size = sizeof(struct format_data) * ssip->sects_per_trk;
  215.     krtn = vm_allocate(task_self(), 
  216.             (vm_address_t *)&fdp,
  217.             format_data_size,
  218.             TRUE);
  219.     if(krtn) {
  220.         printf("\n...Couldn't allocate Format data buffer\n");
  221.         format_abort();
  222.     }
  223.  
  224.     signal(SIGINT, format_abort);
  225.     if(rtn = format_disk(fd, live_fd, &format_info))
  226.         format_abort();
  227.     
  228.     printf("\n..Format Complete\n");
  229.     exit(0);
  230. }
  231.  
  232. void usage(char **argv) {
  233.     printf("usage: %s device [b=blocksize)] [d=density] [g=gap3_length] [n=num_cylinders]\n", argv[0]);
  234.     printf("       blocksize = 512 or 1024\n");
  235.     printf("       density = 720, 1440, 2880\n");
  236.     exit(1);
  237. }
  238.  
  239. void format_abort()
  240. {
  241.     int arg;
  242.     
  243.     /*
  244.      * ctl C or error abort; mark disk as unformatted.
  245.      */
  246.     arg = FD_DENS_NONE;
  247.     if(ioctl(fd, FDIOCSDENS, &arg)) {    /* unformatted */
  248.         perror("ioctl(FDIOCSDENS)");
  249.         exit(1);
  250.     }
  251.     printf("\n..Format Aborted\n");
  252.     exit(1);
  253.  
  254. }
  255. int format_disk(int fd, int live_fd, struct fd_format_info *finfop)
  256. {
  257.     int rtn;
  258.     int cylinder;
  259.     int head;
  260.     int vfy_block=0;
  261.     struct fd_sectsize_info *ssip = &finfop->sectsize_info;
  262.     
  263.     if(cyls_to_format == 0)
  264.         cyls_to_format = format_info.disk_info.num_cylinders;
  265.         
  266.     if(rtn = recalibrate(fd, &format_info)) {
  267.         return(1);
  268.     }
  269.     for(cylinder=0; cylinder<cyls_to_format; cylinder++) {
  270.         for(head=0; 
  271.             head<format_info.disk_info.tracks_per_cyl; 
  272.             head++) {
  273.             if(rtn = format_track(fd, cylinder, head, finfop)) {
  274.                 printf("\n...Format track FAILED\n");
  275.                 printf("  cyl %d  head %d\n", cylinder, head);
  276.                 return(1);
  277.             }
  278.             /*
  279.              * Read the whole track. No data verify; just rely on
  280.              * CRC.
  281.              */
  282.             if(fd_rw(live_fd,
  283.                 vfy_block,
  284.                 ssip->sects_per_trk,
  285.                 vfy_buf,
  286.                 TRUE,
  287.                 finfop))
  288.                 return(1);
  289.             vfy_block += ssip->sects_per_trk;
  290.         }
  291.         printf(".");   
  292.             fflush(stdout);
  293.     }
  294.     return(0);
  295. }
  296.  
  297. /*
  298.  * Format one track.
  299.  */
  300. int format_track(int fd, int cylinder, int head, struct fd_format_info *finfop)
  301. {
  302.     struct format_data *fdp_work;
  303.     int sector;
  304.     struct fd_ioreq ioreq;
  305.     struct fd_format_cmd *cmdp = (struct fd_format_cmd *)ioreq.cmd_blk;
  306.     int data_size;
  307.     int rtn=0;
  308.     struct fd_sectsize_info *ssip = &finfop->sectsize_info;
  309.  
  310.     data_size = sizeof(struct format_data) * ssip->sects_per_trk;
  311.  
  312.     /*
  313.      * Generate the data we'll DMA during the format track command.
  314.      * This consists if the headers for each sector on the cylinder.
  315.      */
  316.     fdp_work = fdp;
  317.     for(sector=1; sector<=ssip->sects_per_trk; sector++) {
  318.         fdp_work->cylinder = cylinder;
  319.         fdp_work->head = head;
  320.         fdp_work->sector = sector;
  321.         fdp_work->n = ssip->n;
  322.         fdp_work++;
  323.     }
  324.     if(seek_com(fd, cylinder * finfop->disk_info.tracks_per_cyl + head, 
  325.         finfop, finfop->density_info.density)) {
  326.         return(1);
  327.     }
  328.     usleep(20000);        /* head settling time - 20 ms (fixme) */
  329.     
  330.     /*
  331.      * Build a format command 
  332.      */
  333.     bzero(&ioreq, sizeof (struct fd_ioreq));
  334.     
  335.     ioreq.density = finfop->density_info.density;
  336.     ioreq.timeout = 5000;
  337.     ioreq.command = FDCMD_CMD_XFR;
  338.     ioreq.num_cmd_bytes = sizeof(struct fd_format_cmd);
  339.     ioreq.addrs = (caddr_t)fdp;
  340. #if    m68k
  341.     ioreq.byte_count = DMA_ENDALIGN(int, data_size);
  342. #else    m68k
  343.     ioreq.byte_count = data_size;
  344. #endif    m68k
  345.     ioreq.num_stat_bytes = SIZEOF_RW_STAT;
  346.     ioreq.flags = FD_IOF_DMA_WR;
  347.     
  348.     cmdp->mfm           = finfop->density_info.mfm;
  349.     cmdp->opcode        = FCCMD_FORMAT;
  350.     cmdp->hds           = head;
  351.     cmdp->n             = ssip->n;
  352.     cmdp->sects_per_trk = ssip->sects_per_trk;
  353.     cmdp->gap_length    = fmt_gap3_length;
  354.     cmdp->filler_data   = 0x5a;
  355.     rtn = do_ioc(fd, &ioreq);
  356.     if(rtn) {
  357.         printf("\n...Format (cylinder %d head %d) Failed\n", 
  358.             cylinder, head);
  359.     }
  360.     return(rtn);
  361. } /* format_track() */
  362.  
  363. int recalibrate(int fd, struct fd_format_info *fip) {
  364.     struct fd_ioreq ioreq;
  365.     struct fd_seek_cmd *cmdp = (struct fd_seek_cmd *)ioreq.cmd_blk;
  366.     int rtn=0;
  367.     
  368.     bzero(&ioreq, sizeof(struct fd_ioreq));
  369.     cmdp->opcode = FCCMD_RECAL;
  370.     ioreq.density = fip->density_info.density;
  371.     ioreq.timeout = 2000;
  372.     ioreq.command = FDCMD_CMD_XFR;
  373.     ioreq.num_cmd_bytes = sizeof(struct fd_recal_cmd);
  374.     ioreq.addrs = 0;
  375.     ioreq.byte_count = 0;
  376.     ioreq.num_stat_bytes = sizeof(struct fd_int_stat);
  377.     rtn = do_ioc(fd, &ioreq);
  378.     if(rtn) {
  379.         printf("\n...Recalibrate Failed\n");
  380.     }
  381.     return(rtn);
  382. }
  383.  
  384. int do_ioc(int fd, fd_ioreq_t fdiop)
  385. {    
  386.     int rtn=0;
  387.     
  388.     fdiop->status = FDR_SUCCESS;
  389.     if (ioctl(fd, FDIOCREQ, fdiop) < 0) {
  390.         perror("ioctl(FDIOCREQ)");
  391.         rtn = 1;
  392.         goto check_status;
  393.     }
  394.     if(fdiop->num_cmd_bytes != fdiop->cmd_bytes_xfr) {
  395.         printf("\n...Expected cmd byte count = 0x%x\n",
  396.              fdiop->num_cmd_bytes);
  397.         printf("   received cmd byte count = 0x%x\n",
  398.             fdiop->cmd_bytes_xfr);
  399.         rtn = 1;
  400.         goto check_status;
  401.     }
  402.     if(fdiop->num_stat_bytes != fdiop->stat_bytes_xfr) {
  403.         printf("\n...Expected cmd byte count = 0x%x\n", 
  404.             fdiop->num_stat_bytes);
  405.         printf("   received cmd byte count = 0x%x\n", 
  406.             fdiop->stat_bytes_xfr);
  407.         rtn = 1;
  408.         goto check_status;
  409.     }
  410.     if(fdiop->byte_count != fdiop->bytes_xfr) {
  411.         printf("\n...Expected byte count = 0x%x\n", fdiop->byte_count);
  412.         printf("   received byte count = 0x%x\n", fdiop->bytes_xfr);
  413.         rtn = 1;
  414.         goto check_status;
  415.     }
  416. check_status:
  417.     if(fdiop->status != FDR_SUCCESS) {
  418.         rtn = 1;
  419.         printf("\n...Unexpected status: %x\n", fdiop->status);
  420.     }
  421.     return(rtn);
  422. }
  423.  
  424. int seek_com(int fd, int track, struct fd_format_info *finfop, int density)
  425. {
  426.     struct fd_ioreq ioreq;
  427.     struct fd_seek_cmd *cmdp = (struct fd_seek_cmd *)ioreq.cmd_blk;
  428.     int rtn = 0;
  429.     
  430.     bzero(&ioreq, sizeof(struct fd_ioreq));
  431.     cmdp->opcode = FCCMD_SEEK;
  432.     cmdp->hds = track % finfop->disk_info.tracks_per_cyl;
  433.     cmdp->cyl = track / finfop->disk_info.tracks_per_cyl;
  434.     ioreq.timeout = 2000;
  435.     ioreq.density = density;
  436.     ioreq.command = FDCMD_CMD_XFR;
  437.     ioreq.num_cmd_bytes = SIZEOF_SEEK_CMD;
  438.     ioreq.num_stat_bytes = sizeof(struct fd_int_stat);
  439.     rtn = do_ioc(fd, &ioreq);
  440.     if(rtn) {
  441.         printf("\n...Seek (track %d) failed\n", track);
  442.     }
  443.     return(rtn);
  444. }
  445.  
  446. #define    USE_LIVE_IO    1
  447.  
  448. #if    USE_LIVE_IO
  449.  
  450. int fd_rw(int fd,
  451.     int block,
  452.     int block_count,
  453.     u_char *addrs,
  454.     boolean_t read_flag,
  455.     struct fd_format_info *finfop)
  456. {
  457.     int         rtn;
  458.     char         *read_str;
  459.     int         byte_count;
  460.     int        offset;
  461.         
  462.     read_str = read_flag ? "read " : "write";
  463.     offset = block * finfop->sectsize_info.sect_size;
  464.     byte_count = block_count * finfop->sectsize_info.sect_size;
  465.     rtn = lseek(fd, offset, L_SET);
  466.     if(rtn != offset) {
  467.         printf("Live Partition Seek Seek error on %s\n", read_str);
  468.         return(1);
  469.     }
  470.     if(read_flag) {
  471.         rtn = read(fd, addrs, byte_count);
  472.     }
  473.     else {
  474.         rtn = write(fd, addrs, byte_count);
  475.     }
  476.     if(rtn != byte_count) {
  477.         printf("\n");
  478.         if(rtn <= 0) {
  479.             perror(read_str);
  480.         }
  481.         else {
  482.             printf("Short %s (exp %d, recd %d)\n",
  483.                 read_str, byte_count, rtn);
  484.         }
  485.         printf("block %d block_count %d\n", block, block_count);
  486.         return(1);
  487.     }
  488.     return(0);
  489. } /* fd_rw() */
  490.  
  491.  
  492. #else    USE_LIVE_IO
  493.  
  494. int fd_rw(int fd,
  495.     int block,
  496.     int block_count,
  497.     u_char *addrs,
  498.     boolean_t read_flag,
  499.     struct fd_format_info *finfop)
  500. {
  501.     int rtn;
  502.     char *read_str;
  503.     int byte_count;
  504.     struct fd_rawio rawio;
  505.     
  506.     read_str = read_flag ? "read " : "write";
  507.         
  508.     rawio.sector = block;
  509.     rawio.sector_count = block_count;
  510.     rawio.dma_addrs = (caddr_t)addrs;
  511.     rawio.read = read_flag;
  512.     rawio.sects_xfr = rawio.status = -1;
  513.     
  514.     rtn = ioctl(fd, FDIOCRRW, &rawio);
  515.     if(rtn) {
  516.         if(read_flag)
  517.             perror("ioctl(FDIOCRW, read)");
  518.         else
  519.             perror("ioctl(FDIOCRW, write)");
  520.         return(1);
  521.             
  522.     }
  523.     if(rawio.status != FDR_SUCCESS) {
  524.         printf("\n...%s: rawio.status = %d(d)\n",
  525.             read_str, rawio.status);
  526.         return(1);
  527.     }
  528.     if(rawio.sects_xfr != block_count) {
  529.         printf("\n...ioctl(FDIOCRW, %s) moved %d(d) blocks, "
  530.             "expected %d(d) blocks\n", 
  531.             read_str, rawio.sects_xfr, block_count);
  532.         return(1);
  533.     }
  534.     return(0);
  535. } /* fd_rw() */
  536.  
  537. #endif    USE_LIVE_IO
  538.  
  539.  
  540.  
  541.  
  542.  
  543.